package com.yhsimon.realm.member.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yhsimon.realm.member.constant.ResultCodeEnum;
import com.yhsimon.realm.member.dto.index.LoginDto;
import com.yhsimon.realm.member.dto.user.UserDto;
import com.yhsimon.realm.member.exception.RealmException;
import com.yhsimon.realm.member.service.UserService;
import com.yhsimon.realm.member.entity.user.UserEntity;
import com.yhsimon.realm.member.mapper.UserMapper;
import com.yhsimon.realm.member.utils.R;
import com.yhsimon.realm.member.vo.index.LoginVo;
import com.yhsimon.realm.member.vo.user.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 19819
 * @description 针对表【mms_member(用户信息表)】的数据库操作Service实现
 * @createDate 2024-04-24 17:25:43
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity>
        implements UserService {


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Override
    public LoginVo login(LoginDto loginDto) {
        // 校验验证码是否正确
        String captcha = loginDto.getCaptcha();     // 用户输入的验证码
        String codeKey = loginDto.getCodeKey();     // redis中验证码的数据key

        // 从Redis中获取验证码
        String redisCode = (String) redisTemplate.opsForValue().get("user:login:validatecode:" + codeKey);
        if (StrUtil.isEmpty(redisCode) || !StrUtil.equalsIgnoreCase(redisCode, captcha)) {
            throw new RealmException(ResultCodeEnum.VALIDATE_CODE_ERROR);
        }
        // 验证通过删除redis中的验证码
        redisTemplate.delete("user:login:validatecode:" + codeKey);
        UserEntity userEntity = userMapper.selectByUserName(loginDto.getUserName());
        if (userEntity == null) {
            throw new RealmException(ResultCodeEnum.LOGIN_ERROR);
        }

        String inputPassword = loginDto.getPassword();
        String md5InputPassword = DigestUtils.md5DigestAsHex(inputPassword.getBytes());
        if (!md5InputPassword.equals(userEntity.getPassword())) {
            throw new RealmException(ResultCodeEnum.LOGIN_ERROR);
        }

        // 生成令牌，保存数据到Redis
        String token = UUID.randomUUID().toString().replace("-", "");
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(userEntity,userDto);
        redisTemplate.opsForValue().set("user:login:" + token, JSON.toJSONString(userDto), 30, TimeUnit.MINUTES);


        LoginVo loginVo = LoginVo.builder()
                .token(token)
                .refresh_token("").build();
        return loginVo;
    }

    @Override
    public void logout(String token) {
        redisTemplate.delete("user:login:" + token);
    }

    @Override
    public R signIn(String userId) {
        UserEntity userEntity = userMapper.selectById(userId);
        Date createTime = userEntity.getCreateTime();
        LocalDate createDate = convertDateToLocalDate(createTime);
        LocalDate nowDate = LocalDate.now();
        // log.info("timeZone:{}", TimeZone.getDefault());
        // log.info("nowDate: {}",nowDate);
        long daysBetween = Math.abs(ChronoUnit.DAYS.between(createDate, nowDate));

        if (Boolean.TRUE.equals(redisTemplate.opsForValue().getBit("user:signIn:" + userId, daysBetween))) {
            return R.ok("今日已签到");
        }
        redisTemplate.opsForValue().setBit("user:signIn:" + userId, daysBetween, true);
        return R.ok("签到成功");
    }

    @Override
    public int[] getSignInStatus(String userId) {
        UserEntity userEntity = userMapper.selectById(userId);
        LocalDate createDate = convertDateToLocalDate(userEntity.getCreateTime());
        LocalDate nowDate = LocalDate.now();
        LocalDate firstDayOfMonth = LocalDate.now().withDayOfMonth(1);

        long startDaysBetween = Math.abs(ChronoUnit.DAYS.between(createDate, firstDayOfMonth));

        long curDaysBetween = Math.abs(ChronoUnit.DAYS.between(createDate, nowDate));


        // bitmap的遍历开始的下标
        long offset = startDaysBetween;
        // 状态status数组遍历的开始下标
        int index = 0;
        // 如果用户创建时间在本月1号之后
        if (createDate.isAfter(firstDayOfMonth)||createDate.isEqual(firstDayOfMonth)) {
            offset = 0L;
            index = (int) startDaysBetween;
        }
        int len = (int) (ChronoUnit.DAYS.between(firstDayOfMonth, nowDate));
        int[] status = new int[len + 1];
        for (; offset <= curDaysBetween && index < len + 1; offset++, index++) {
            if (Boolean.TRUE.equals(redisTemplate.opsForValue().getBit("user:signIn:" + userId, offset))) {
                status[index] = 1;
            }
        }
        return status;
    }

    // 将Date转换为LocalDate的辅助方法
    private static LocalDate convertDateToLocalDate(Date date) {
        return date.toInstant().atZone(java.util.TimeZone.getDefault().toZoneId()).toLocalDate();
    }


    public static void main(String[] args) {
        LocalDate nowDate = LocalDate.now();
        LocalDate firstDayOfMonth = LocalDate.now().withDayOfMonth(1);
        // int len = (int) (ChronoUnit.DAYS.between(firstDayOfMonth, nowDate));
        int len = (int) (ChronoUnit.DAYS.between(nowDate,firstDayOfMonth));
        log.info("firstDayOfMonth {}", firstDayOfMonth);
        log.info("nowDate {}", nowDate);
        log.info("{}", len);
    }


}




